home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
FLOATING
/
PROCEDUR
/
SOURCE_C
/
FLOATING.C
next >
Wrap
Text File
|
1990-10-30
|
15KB
|
520 lines
/********************************************************************
FLOATING WINDOWS 1.3
Copyright 1990 Patrick Doane. All Rights Reserved
********************************************************************/
#include "Floating.h"
WindowPtr bottomFloat,topFloat,topWindow;
RgnHandle drawRgn,windowRgn,dragRgn;
GrafPtr wPort;
Rect dragRect;
void InitFloat(void)
{
/* Initialize all of the internal variables */
drawRgn = NewRgn();
windowRgn = NewRgn();
dragRgn = NewRgn();
wPort = (GrafPtr)NewPtrClear(sizeof(GrafPort));
OpenPort(wPort);
topFloat = 0L;
bottomFloat = 0L;
topWindow = 0L;
dragRect = (**GetGrayRgn()).rgnBBox;
InsetRect(&dragRect,4,4);
}
void UpdateTopWindow(void)
{
if (bottomFloat)
topWindow = (WindowPtr)((WindowPeek)bottomFloat)->nextWindow;
else
topWindow = FrontWindow();
}
void UpdateFloats(void)
{
WindowPeek theWindow;
topFloat = 0L; /* Clear variables */
bottomFloat = 0L;
theWindow = (WindowPeek)FrontWindow(); /* Start with the front window */
if (IsFloating((WindowPtr)theWindow)) /* Is it a floating window? */
{ topFloat = (WindowPtr)theWindow; /* Yep, let's start figuring
out our list starting with
that one */
while (IsFloating((WindowPtr)theWindow))
{ /* Continue updating our bottom pointer until we have found the
the last window */
bottomFloat = (WindowPtr)theWindow;
theWindow = theWindow->nextWindow;
if (!theWindow)
break;
}
}
}
WindowPtr NewFloatingWindow(short ResID,Ptr wStorage)
{
WindowPtr theWindow;
/* Bring it into existance */
theWindow = GetNewWindow(ResID,wStorage,0L);
BringToFront(theWindow); /* Floating window must be in front */
ShowHide(theWindow,true); /* Make sure it is visible */
if (!topFloat) /* If topFloat is 0L then this is the
the first floating window to be
made. Since it is the first, it must
also be the last */
bottomFloat = theWindow;
topFloat = theWindow; /* Mark it is as the top floating window */
MakeFloating(theWindow); /* And mark it as a floating window */
return theWindow; /* Return reference to theWindow */
}
void MakeFloating(WindowPtr whichWindow)
{
/* Mark it as a floating window */
((WindowPeek)whichWindow)->windowKind = 317;
BringToFront(whichWindow); /* Floating window must be in front */
}
Boolean IsFloating(WindowPtr whichWindow)
{
/* Is it a floating window? */
return (((WindowPeek)whichWindow)->windowKind == 317);
}
void CloseTheWindow(WindowPtr whichWindow)
{
register WindowPeek theWindow;
CloseWindow(whichWindow);
/* Calculate the next window to hilite. Start with the next window
behind the one you are closing. Continue until you find the first
visable one. */
theWindow = ((WindowPeek)whichWindow)->nextWindow;
if (theWindow)
{ while (!theWindow->visible)
{ theWindow = theWindow->nextWindow;
if (!theWindow)
break;
}
}
/* If we got a window (other than 0L) then Hilite it and tell the
toolbox to activate that window */
if (theWindow)
{ HiliteWindow(theWindow,true);
CurActivate = (WindowPtr)theWindow;
/* Since one of the windows that was killed could have been a floating
window. We rebuild that list starting with the frontmost window
and working the way through the list until we find the first
nonfloating window which marks the end of the floats. */
UpdateFloats();
}
else /* We have no windows left so hide our floats */
HideFloats();
UpdateTopWindow();
}
void DisposeTheWindow(WindowPtr whichWindow)
{
register WindowPeek theWindow;
DisposeWindow(whichWindow);
/* Calculate the next window to hilite. Start with the next window
behind the one you are closing. Continue until you find the first
visable one. */
theWindow = ((WindowPeek)whichWindow)->nextWindow;
if (theWindow)
{ while (!theWindow->visible)
{ theWindow = theWindow->nextWindow;
if (!theWindow)
break;
}
}
/* If we got a window (other than 0L) then Hilite it and tell the
toolbox to activate that window */
if (theWindow)
{ HiliteWindow((WindowPtr)theWindow,true);
CurActivate = (WindowPtr)theWindow;
/* Since one of the windows that was killed could have been a floating
window. We rebuild that list starting with the frontmost window
and working the way through the list until we find the first
nonfloating window which marks the end of the floats. */
UpdateFloats();
}
else /* We have no windows left so hide our floats */
HideFloats();
UpdateTopWindow();
}
void ShowTheWindow(WindowPtr whichWindow)
{
ShowWindow(whichWindow); /* Call Toolbox Procedure */
if (whichWindow == (WindowPtr)((WindowPeek)bottomFloat)->nextWindow)
/* If the window is now the
top nonfloating window,
Hilite it */
HiliteWindow(whichWindow,true);
UpdateFloats();
}
void HideTheWindow(WindowPtr whichWindow)
{
register WindowPeek theWindow;
HideWindow(whichWindow); /* Call Toolbox procedure */
/* Start with the next window behind the one we are hiding.
Continue searching until we find a visible one. */
theWindow = ((WindowPeek)whichWindow)->nextWindow;
while (!theWindow->visible)
{ theWindow = theWindow->nextWindow;
if (!theWindow)
break;
}
if (theWindow) /* If we found a window, Hilite it */
HiliteWindow(theWindow,true);
UpdateFloats();
}
void ShowFloats(void)
{
register WindowPeek theWindow;
if (topFloat) /* Do we have floating windows? */
{ theWindow = (WindowPeek)topFloat; /* Start with the top one */
while (theWindow != ((WindowPeek)bottomFloat)->nextWindow)
/* Contine until we reach the
last floating window */
{ /* Show the window and move
on to the next */
ShowHide((WindowPtr)theWindow,true);
theWindow = theWindow->nextWindow;
if (!theWindow)
break;
}
}
}
void HideFloats(void)
{
register WindowPeek theWindow;
if (topFloat) /* Do we have floating windows? */
{ theWindow = (WindowPeek)topFloat; /* Start with the top one */
while (theWindow != ((WindowPeek)bottomFloat)->nextWindow)
/* Contine until we reach the
last floating window */
{ /* Hide the window and move
on to the next */
ShowHide((WindowPtr)theWindow,false);
theWindow = theWindow->nextWindow;
if (!theWindow)
break;
}
}
}
WindowPtr CurrentWindow(void)
{
return topWindow; /* Just return our variable */
}
void SelectTheWindow(register WindowPtr whichWindow)
{
Boolean floating; /* Is it a floating window */
register WindowPeek bottomPeek; /* Reference to bottom float */
register WindowPeek theWindowPeek; /* Generic reference to window */
WindowPtr lastTop; /* The last top window */
register WindowPeek beforePeek; /* The location of where the
the window will be moved */
GrafPtr savePort;
floating = IsFloating(whichWindow); /* Is it a floating window? */
if (floating)
{ if (whichWindow != topFloat)
{ /* If it is not the front floating window, bring it to the front */
BringToFront(whichWindow);
topFloat = whichWindow;
/* and find the last floating window */
theWindowPeek = (WindowPeek)whichWindow;
while (IsFloating((WindowPtr)theWindowPeek))
{ bottomFloat = (WindowPtr)theWindowPeek;
theWindowPeek = theWindowPeek->nextWindow;
}
}
}
else
{ if (!bottomFloat) /* if there are no other floating windows
just bring it to the front. */
{ if (whichWindow != FrontWindow())
SelectWindow(whichWindow);
}
else
{ bottomPeek = (WindowPeek)bottomFloat;
theWindowPeek = (WindowPeek)whichWindow;
if (theWindowPeek != bottomPeek->nextWindow)
{ /* It's not the top document window, now we find what
that is */
lastTop = (WindowPtr)bottomPeek->nextWindow;
/* Create deactivate event for last active document window */
CurDeactive = lastTop;
HiliteWindow(lastTop,false);
/* Now we rewrite the window list to change the location
of the window. First we find the window that was before
the window we want to move. We then set its nextWindow
field to the window in front of the window we are moving.
That then removes the window from the window list.
Now we want to place it rigth after the bottommost
floating window. To do that, we set the nextWindow
field of the window we are moving to the window right
after the bottommost floating window and set the nextWindow
field of the bottommost floating window to the window
we are moving. Confusing eh? */
beforePeek = bottomPeek->nextWindow;
while (beforePeek->nextWindow != theWindowPeek)
beforePeek = beforePeek->nextWindow;
beforePeek->nextWindow = theWindowPeek->nextWindow;
theWindowPeek->nextWindow = bottomPeek->nextWindow;
bottomPeek->nextWindow = theWindowPeek;
/* Now we have to recalculate all the visible regions
and redraw newly exposed areas */
GetPort(&savePort);
SetPort(whichWindow);
/* We start with the visible region of our window but
unfortunately, it is in local coordinates of the
window so we convert it to global by using the GlobalRgn
procedure */
CopyRgn(whichWindow->visRgn,drawRgn);
GlobalRgn(drawRgn);
/* We then subtract the visible region of the window
from the windows structure region. This gives us
the area which is being brought to the front */
DiffRgn(theWindowPeek->strucRgn,drawRgn,drawRgn);
/* Paint the area and hilite it to show it is now active */
PaintOne(whichWindow,drawRgn);
HiliteWindow(whichWindow,true);
/* PaintOne sets thePort to the Window Manager Port so
we must reset thePort to whichWindow. We then call
CalcWindowVis which will recalculate all the visible
regions */
SetPort(whichWindow);
CalcWindowVis(theWindowPeek);
/* Then invalidate the region so that it will update
properly */
InvalRgn(drawRgn);
SetPort(savePort);
/* And finally, generate another event to activate the
new window */
CurActivate = whichWindow;
}
}
}
if (!((WindowPeek)whichWindow)->visible) /* A little kludge
has been added for floating window support
which makes sure to make the window visible
if it is hidden */
ShowHide(whichWindow,true);
UpdateTopWindow(); /* Rebuild our window list */
}
void DragTheWindow(WindowPtr whichWindow,EventRecord *theEvent)
{
GrafPtr savePort; /* Saved graphics pointer */
Point thePoint; /* Used to remember the original
location of the window */
long newLoc; /* Window's new position */
short hDelta,vDelta; /* How much to move the window */
register WindowPeek theWindow;
/* Since dragging a window automatically brings it to the front
unless you are holding the command key down, this routine needs
to be redone. Otherwise it would kill the floating window
relationship */
/* If it's a floating window and not the front floating window
and the command key is not down, bring it to the front before
draggin */
if (IsFloating(whichWindow))
{ if (whichWindow != topFloat && !(theEvent->modifiers & cmdKey))
SelectTheWindow(whichWindow);
}
/* if the window is not the front document window and the command
key is not down, select the window and exit */
else if (!topFloat)
{ if (whichWindow != FrontWindow() && !(theEvent->modifiers & cmdKey))
{ SelectWindow(whichWindow);
return;
}
}
else if (whichWindow != (WindowPtr)((WindowPeek)bottomFloat)->nextWindow
&& !(theEvent->modifiers & cmdKey))
{ SelectTheWindow(whichWindow);
return;
}
if (!StillDown())
return;
GetPort(&savePort);
SetPort(whichWindow);
/* remember the top-left coordinate of the window */
thePoint = topLeft(whichWindow->portRect);
LocalToGlobal(&thePoint);
/* Copy the window's structure region to be used for dragging */
CopyRgn(((WindowPeek)whichWindow)->strucRgn,dragRgn);
/* Use our graphics port */
SetPort(wPort);
/* We must figure out the drag region for the window.
Start with the top window and work or way through the window
list altering our graphics port to the screen's visible region.
This effectively gives us a visible region of the screen minus
that of all windows above the window we are dragging */
CopyRgn(GetGrayRgn(),wPort->visRgn);
theWindow = (WindowPeek)FrontWindow();
if (theWindow != (WindowPeek)whichWindow)
{ DiffRgn(wPort->visRgn,theWindow->strucRgn,wPort->visRgn);
while (theWindow != (WindowPeek)whichWindow)
{ DiffRgn(wPort->visRgn,theWindow->strucRgn,wPort->visRgn);
theWindow = theWindow->nextWindow;
}
}
/* drag the window */
newLoc = DragGrayRgn(dragRgn,theEvent->where,&dragRect,&dragRect,
noConstraint,0L);
if (newLoc != 0x80008000)
{ hDelta = LoWord(newLoc);
vDelta = HiWord(newLoc);
/* If the window moved, move it */
if (hDelta || vDelta)
MoveWindow(whichWindow,hDelta+thePoint.h,vDelta+thePoint.v,false);
}
SetPort(savePort);
}
void CalcWindowVis(register WindowPeek whichWindow)
{
register WindowPeek theWindow;
GrafPtr savePort;
GetPort(&savePort);
/* First we start with an empty region. From there we begin with
the front window which would be one of the floating windows
and add its structure region to windowRgn. We continue to add
in the regions until we reach whichWindow */
SetEmptyRgn(windowRgn);
theWindow = (WindowPeek)FrontWindow();
while (theWindow != whichWindow)
{ UnionRgn(windowRgn,theWindow->strucRgn,windowRgn);
theWindow = theWindow->nextWindow;
}
/* We now have all the regions of all the windows in front of
whichWindow. To calculate the visible region of whichWindow,
we copy its content region (which is in global coordinates) into
the visRgn field. We then SUBTRACT the region we generated before
from the visible region of the window. Finally, convert it into
local coordinates for the toolbox */
SetPort(whichWindow);
CopyRgn(whichWindow->contRgn,whichWindow->port.visRgn);
DiffRgn(whichWindow->port.visRgn,windowRgn,whichWindow->port.visRgn);
LocalRgn(whichWindow->port.visRgn);
/* Now we have to calculate all the visible regions for all windows
behind whichWindow. We just go through the same process again
and again, but each time we add the window's structure region
into windowRgn to subtract again. */
theWindow = whichWindow;
while (theWindow->nextWindow)
{ UnionRgn(windowRgn,theWindow->strucRgn,windowRgn);
theWindow = theWindow->nextWindow;
SetPort(theWindow);
CopyRgn(theWindow->contRgn,theWindow->port.visRgn);
DiffRgn(theWindow->port.visRgn,windowRgn,theWindow->port.visRgn);
LocalRgn(theWindow->port.visRgn);
}
SetPort(savePort);
}
void GlobalRgn(register RgnHandle changeRgn)
{
register Rect theRect;
/* Converts a region into Global Coordinates */
theRect = thePort->portBits.bounds;
OffsetRgn(changeRgn,-theRect.left,-theRect.top);
}
void LocalRgn(register RgnHandle changeRgn)
{
register Rect theRect;
/* Converts a region into Global Coordinates */
theRect = thePort->portBits.bounds;
OffsetRgn(changeRgn,theRect.left,theRect.top);
}